package main;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Scanner;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import modex.Paragraphe;
import modex.Terme;
import modex.TermePara;

import org.xml.sax.SAXException;

import parser.ParserTermeHandler;
import parser.TFIDF;
import recherche.ModuleRecherche;
import bddaccess.BDDAccess;

public class ParserMain {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try{		
			Scanner scanner = new Scanner(System.in);
			
	    	// Calcul du temps de départ
	    	long begin = System.currentTimeMillis();
	    	
	    	/* PHASE DE PARSAGE */
	    	
		    // création d'une fabrique de parseurs SAX
	        SAXParserFactory fabrique = SAXParserFactory.newInstance();
	
	        // création d'un parseur SAX
	        SAXParser parseur = fabrique.newSAXParser();

	        // Création d'un filtre pour récupérer les documents xml du corpus
	        FilenameFilter filter = new FilenameFilter() {
			
				@Override
				public boolean accept(File dir, String name) {
					return (name.startsWith("d") && name.endsWith(".xml"));
				}
			};
			
	        // Répertoire des fichiers
	        File directory = new File("./resources/");
	               
	        // Récupération des fichiers xml
	        File[] files = directory.listFiles(filter);
	        
	        // Création du parser
	        ParserTermeHandler gestionnaire = new ParserTermeHandler();

	        // Parsage des documents
	        System.out.println("Parsing...");
	        for (File currentFile : files) {
//	        	System.out.println("Parsing doc "+currentFile.getName()+"...");
	        	gestionnaire.createDocument(currentFile.getName());
		        parseur.parse(currentFile, gestionnaire);
	        }

//	        TODO REMOVE :
//	        gestionnaire.createDocument(files[0].getName());
//	        parseur.parse(files[0], gestionnaire);
	        
            /* CALCUL DES SCORES */

//    		TODO : REMOVE
//	        int nbTotalPara = paraDao.count();
			int nbTotalPara = gestionnaire.getParagraphes().size();
//	        System.out.println("nbTotalPara :\t"+nbTotalPara);
	        
	        int idLastPara = 0;
	        int idLastTerme = 0;
	        int nbTermsInPara = 0;
	        int nbParasWithTerm = 0;
	        int i = 0;
	        boolean found = false;
	        
	        // TODO Faire une classe pour le calcul des scores
	        
	        System.out.println("Calculating scores...");
	        ArrayList<Terme> termes = new ArrayList<Terme>(gestionnaire.getTermes().values());
	        ArrayList<TermePara> termesParas = new ArrayList<TermePara>(gestionnaire.getTermeParas().values());
	        
	        for (TermePara tp : termesParas) {
	        	// Nombre de fois ou le terme apparaît dans le paragraphe;
	        	int nbOccurr = tp.getPoids();
//	        	System.out.println("Poids du terme :\t\t" + nbOccurr);
	        	
	        	// On recalcule le nombre de termes que si le paragraphe est différent
	        	if (tp.getIdPara() != idLastPara) {
	        		// Nombre total de termes dans le paragraphe
	        		nbTermsInPara = gestionnaire.getParagraphes().get(tp.getIdPara()).getNbTermes();
	        		idLastPara = tp.getIdPara();
	        		
//	        		TODO : REMOVE
//	        		nbTermsInPara = termParaDao.nbTermesInPara(tp.getIdPara());
//		        	nbTermsInPara = gestionnaire.getNbTermsInPara(tp.getIdPara());
		        	
//		        	System.out.println("NB termes du para :\t\t" + nbTermsInPara);	        		
	        	}
	        	// On recalcule le nombre de paragraphes que si le terme est différent
	        	if (tp.getIdTerme() != idLastTerme) {
		            // Nombre de paragraphes avec ce terme
//	        		nbParasWithTerm = gestionnaire.getTermes().get(tp.getIdTerme()).getNbParagraphes();
	        		i = 0;
	        		found = false;
	        		// On cherche le terme correspondant à ce TermePara et on récupère le nombre de paragraphes dans lequel il apparaît
	        		while ((i<termes.size()) && (found == false)) {
	        			if (termes.get(i).getIdTerme() == tp.getIdTerme()){
	        				nbParasWithTerm = termes.get(i).getNbParagraphes();
	        				found = true;
	        			}
	        			i++;
	        		}
//	        		for (Terme t : termes){
//	        			if (t.getIdTerme() == tp.getIdTerme()){
//	        				nbParasWithTerm = t.getNbParagraphes();
//	        			}
//	        		}
	        		idLastTerme = tp.getIdTerme();
	        		
//	        		TODO : REMOVE
//	        		nbParasWithTerm = termParaDao.nbParagrafWithTerm(tp.getIdTerme()); 
//	        		nbParasWithTerm = gestionnaire.getNbParasWithTerm(tp.getIdTerme());
		        	
//		        	System.out.println("NB paras avec ce terme :\t" + nbParasWithTerm);
	        	}

	        	TFIDF tfidf = new TFIDF(nbOccurr, nbTermsInPara, nbTotalPara, nbParasWithTerm);
//	        	System.out.println("tfidf :\t\t\t\t" + tfidf.getValue()+"\n");
//	        	TODO : REMOVE
//	        	termParaDao.updateScore(tfidf.getValue(), tp.getIdPara(), tp.getIdTerme());
	        	Float tfidfValue = tfidf.getValue();
	        	// Si la valeur est Infinie (nombre de termes du para = 0) on laisse la valeur par défaut (0f)
	        	if (!tfidfValue.isInfinite()){
	        		tp.setScore(tfidfValue);
	        	}
	        }

	        /* IMPLANTATION DE L'INDEX */
	        
	        // Insertion en base de toutes les listes de ParserTermeHandler	        
	        BDDAccess access = new BDDAccess();

	        System.out.println("Implementing the index...");
	        

	        access.insertMultipleBDD(termes);
	        access.insertMultipleBDD(gestionnaire.getDocuments());
	        access.insertMultipleBDD(new ArrayList<Paragraphe>(gestionnaire.getParagraphes().values()));
	        access.insertMultipleBDD(termesParas);

	        // Calcul du temps final
	    	long end = System.currentTimeMillis();

	    	float time = ((float) (end-begin)) / 1000f;
	    	System.out.println("Temps d'exécution : "+time+" secondes");
	    	
	    	/* ETAPE DE RECHERCHE */
	    	
	    	ModuleRecherche moduleRecherche = new ModuleRecherche();

	    	// Récupération requête
	    	String query;
	    	do{
	    		System.out.println("Veuillez saisir votre liste de mots clés :");
	    		query = scanner.nextLine();
	    	}while(query.isEmpty()); 
	    	
	    	// Extraction des mots clés
	    	moduleRecherche.executeQuery(query);

		}catch(ParserConfigurationException pce){
		        System.out.println("Erreur de configuration du parseur");
		        System.out.println("Lors de l'appel à newSAXParser()");
		}catch(SAXException se){
		        System.out.println("Erreur de parsing");
		        System.out.println("Lors de l'appel à parse()");
		}catch(IOException ioe){
		        System.out.println("Erreur d'entrée/sortie");
		        System.out.println("Lors de l'appel à parse()");
		}
	}
}
